package com.starblink.wishlist.wishlistdetails.ui

import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.apollographql.apollo3.api.Optional
import com.kunminx.architecture.domain.message.MutableResult
import com.starblink.android.basic.base.BaseViewModel
import com.starblink.basic.apollo.ext.ApolloExt.findErrorCode
import com.starblink.android.basic.ext.toast
import com.starblink.android.basic.network.base.BaseApiCodeAndUrl
import com.starblink.android.basic.network.base.SkGqlClient
import com.starblink.basic.apollo.ext.optional
import com.starblink.android.basic.util.bus.FlowBus
import com.starblink.android.basic.util.bus.FlowConst
import com.starblink.basic.util.log.YYLogUtils
import com.starblink.library.widget.wishlist.bean.BatchProductArrEntry
import com.starblink.library.widget.wishlist.bean.WishlistRenameEntry
import com.starblink.rocketreserver.*
import com.starblink.rocketreserver.fragment.AccountF
import com.starblink.rocketreserver.fragment.WishListF
import com.starblink.rocketreserver.type.CollectItem
import com.starblink.rocketreserver.type.CollectionProductQueryParam
import com.starblink.rocketreserver.type.GuessYouLikeProductByWishListParam
import com.starblink.rocketreserver.type.WishListUpdateRequest
import com.starblink.wishlist.wishboards.ui.bean.*
import com.starblink.wishlist.wishlistdetails.ui.bean.RvBoardDetailsItemEntry
import kotlinx.coroutines.async
import kotlinx.coroutines.launch

class WishlistDetailsVM : BaseViewModel() {
    var mAllItemsObserver: MutableLiveData<ArrayList<Any>> = MutableLiveData()

    var pageTopIndex = 1
    var pageTopSize = 10
    var pageRelatedIndex = 1

    //记录feeds流总条数
//    var lastFeedsSize = 0

    //心愿单ID
    var mWishlistId: String? = null

    //用户ID
    var mAccountId: String? = null

    private var mWishTotalNum: Int = 0

    //是否自动加载更多
    var autoLoadMoreWish = false
    var autoLoadMoreGuess = false

    //心愿单加载完成后再加载猜你喜欢 但是这里因为失效商品 非常非常之蛋疼
    var wishDataHasComplete = false

    var firstPageDataForGuess: List<GuessYouLikeProductByWishListQuery.GuessYouLikeProductByWishList>? =
        null

    var hasAddRelatedTitle = false
    var hasNext: Boolean? = null

    /****************多选相关 ↓↓↓↓↓↓↓↓↓ ****************************/
    var choiceMode = false

    var selectAll = false
    var choiceNum = 0

    var recordIds = hashSetOf<String>()
    var record2Items = arrayListOf<RvBoardDetailsItemEntry>()

    var addRelateIndex = -1

    /****************多选相关 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑ ****************************/


    fun initSomeData(
        boardItemData: WishListF?,
        accountId: String?,
    ) {
        mWishlistId = boardItemData?.id
        mWishTotalNum = boardItemData?.productCount ?: 0
        mAccountId = accountId
        if (mAllItemsObserver.value == null) {
            mAllItemsObserver.value = arrayListOf(RvNoBoardsEntry())
        }
    }

    /**
     * 设置列表初始数据
     * @note 先将列表控件相关初始化完成，在执行本方法
     */
    fun initListData() {

    }

    /**
     * 刷新的同时 获取第一页的推荐数据 这样比较好处理 加载数据的过渡会比较平滑
     */
    inline fun initRefresh(showDialog: Boolean = false, crossinline hasFinish: () -> Unit) {
        autoLoadMoreWish = false

        viewModelScope.launch {
            pageTopIndex = 1
            pageRelatedIndex = 1
            feedsPositionTag = 0
            val items = async {
                return@async SkGqlClient.skQuery(
                    FetchCollectProductsByAccountIdV3Query(
                        collectionProductQueryParam = CollectionProductQueryParam(
                            accountId = Optional.present(mAccountId),
                            wishListId = Optional.present(mWishlistId),
                            pageNo = Optional.present(pageTopIndex),
                            pageSize = Optional.present(pageTopSize)
                        )
                    ),
                    showDefaultLoading = showDialog
                    //fetchPolicy = FetchPolicy.NetworkFirst
                )?.data?.fetchCollectProductsByAccountIdV3
            }.await()

            //获取推荐
            val guessLike = async {
                return@async SkGqlClient.skQuery(
                    GuessYouLikeProductByWishListQuery(
                        params = GuessYouLikeProductByWishListParam(
                            pageNo = 1,
                            pageSize = 20,
                            wishListId = Optional.present(mWishlistId)
                        )
                    ),
                    //fetchPolicy = FetchPolicy.NetworkFirst
                    showFailToast = false,
                    showErrorToast = false
                )?.data?.guessYouLikeProductByWishList
            }.await()

            combineBoardsAndRelate(items, guessLike, hasFinish = {
                hasFinish.invoke()
            })

        }
    }


    inline fun combineBoardsAndRelate(
        data: FetchCollectProductsByAccountIdV3Query.FetchCollectProductsByAccountIdV3?,
        guessLike: List<GuessYouLikeProductByWishListQuery.GuessYouLikeProductByWishList>?,
        crossinline hasFinish: () -> Unit,
    ) {
        mAllItemsObserver.value!!.clear()
        hasAddRelatedTitle = false
        hasNext = data?.hasNext

        if (data?.productList.isNullOrEmpty()) {
            mAllItemsObserver.value!!.add(RvNoBoardsEntry())
        } else {
            data!!.productList!!.forEach {
                mAllItemsObserver.value!!.add(
                    RvBoardDetailsItemEntry(
                        wishItem = it.productF,
                        showCheckMode = choiceMode,
                        hasChoice = if (selectAll) true else (recordIds.contains(
                            it.productF.id
                        )),
//                        position = mAllItemsObserver.value!!.size
                    )
                )
            }
        }
        //保存第一页的推荐数据
        pageRelatedIndex = 1
        firstPageDataForGuess = guessLike
        feedsPositionTag = 0

        //判断是否心愿单列表数据尚未全部取得
        if (canLoadGuessData()) {
            addRelatedGuessData()
        }
        mAllItemsObserver.postValue(mAllItemsObserver.value)
        hasFinish.invoke()
    }


    inline fun loadMoreWishList(crossinline hasFinish: () -> Unit) {
        viewModelScope.launch {
            pageTopIndex++
            var lastId: String? = null

            if (mAllItemsObserver.value!!.isNotEmpty()) {
                var it1 = mAllItemsObserver.value!!.last()
                if (it1 is RvBoardDetailsItemEntry) {
                    lastId = it1.wishItem.collectRecordId
                }
            }
            val items = SkGqlClient.skQuery(
                FetchCollectProductsByAccountIdV3Query(
                    collectionProductQueryParam = CollectionProductQueryParam(
                        accountId = Optional.present(mAccountId),
                        wishListId = Optional.present(mWishlistId),
//                        pageNo = Optional.present(pageTopIndex),
                        pageSize = Optional.present(pageTopSize),
                        lastId = lastId.optional()
                    )

                ),
                //fetchPolicy = FetchPolicy.NetworkFirst
            )?.data?.fetchCollectProductsByAccountIdV3

            hasNext = items?.hasNext
            if (!items?.productList.isNullOrEmpty()) {
                items!!.productList!!.forEach {
                    mAllItemsObserver.value!!.add(
                        RvBoardDetailsItemEntry(
                            wishItem = it.productF,
                            showCheckMode = choiceMode,
                            hasChoice = if (selectAll) true else (recordIds.contains(
                                it.productF.id
                            )),
//                            position = mAllItemsObserver.value!!.size
                        )
                    )
                }
            }

            if (canLoadGuessData()) {
                addRelatedGuessData()
            }
            mAllItemsObserver.postValue(mAllItemsObserver.value)
            hasFinish.invoke()
        }
    }


    fun canLoadGuessData(): Boolean {
        autoLoadMoreGuess = false


//        YYLogUtils.e(" 9527  ------- $mWishTotalNum   $hasNext")
        //空心愿单
        if (mWishTotalNum == 0) {
            autoLoadMoreGuess = true
            return true
            //没有失效数据 || 总条数小于分页数据
        } else if (hasNext != true) {
            autoLoadMoreGuess = true
            return true
        }
//        if (mWishTotalNum == 0) {
//            autoLoadMoreGuess = true
//            return true
//            //没有失效数据 || 总条数小于分页数据
//        } else if (mAllItemsObserver.value!!.size == mWishTotalNum || mWishTotalNum <= pageTopSize) {
//            autoLoadMoreGuess = true
//            return true
//            //存在失效商品 用是否加载到最后分页判断 向上取整
//        } else if (ceil(mWishTotalNum / pageTopSize.toDouble()).toInt() == pageTopIndex) {
//            autoLoadMoreGuess = true
//            return true
//        }
        return false
    }

    var feedsPositionTag = 0

    fun addRelatedGuessData() {
        firstPageDataForGuess?.let {
            if (it.isNotEmpty()) {
                addRelateIndex = mAllItemsObserver.value!!.size
                mAllItemsObserver.value!!.add(RvRelatedTitleEntry())
                hasAddRelatedTitle = true
                it.forEachIndexed { i, prd ->
                    mAllItemsObserver.value!!.add(
                        RvBoardProductEntry(
                            position = i + feedsPositionTag,
                            product = prd.productF,
                            feedType = 3
                        )
                    )
                }
                feedsPositionTag = it.size
            }
        }
    }

    inline fun loadMoreGuess(crossinline hasFinish: () -> Unit) {
        viewModelScope.launch {
            pageRelatedIndex++
            val moreRelated = SkGqlClient.skQuery(
                GuessYouLikeProductByWishListQuery(
                    params = GuessYouLikeProductByWishListParam(
                        pageNo = pageRelatedIndex,
                        pageSize = 20,
                        wishListId = Optional.present(mWishlistId)
                    )
                ),
                //fetchPolicy = FetchPolicy.NetworkFirst
                showFailToast = false,
                showErrorToast = false
            )?.data?.guessYouLikeProductByWishList
            if (!moreRelated.isNullOrEmpty()) {
                if (!hasAddRelatedTitle) {
                    addRelateIndex = mAllItemsObserver.value!!.size
                    mAllItemsObserver.value!!.add(RvRelatedTitleEntry())
                    hasAddRelatedTitle = true
                }

                moreRelated.forEachIndexed { i, prd ->
                    mAllItemsObserver.value!!.add(
                        RvBoardProductEntry(
                            position = i + feedsPositionTag,
                            product = prd.productF,
                            feedType = 3
                        )
                    )
                }
                feedsPositionTag += moreRelated.size
                mAllItemsObserver.postValue(mAllItemsObserver.value)
                hasFinish.invoke()
            } else {
                hasFinish.invoke()
                pageRelatedIndex--
            }
        }
    }

    //批量删除心愿单
    //# 批量移动商品从心愿单A到心愿单B。前提: 原本已收藏 [登录态]
    //    # 0 到 a, 表示把商品从 allItems 加到 心愿单A
    //    # a 到 b, 表示把商品从 心愿单A  移到 心愿单B
    //    # a 到 0, 表示把商品从 心愿单A 移除
    //    moveProductList2WishList(items:[CollectItem], "from心愿单Id" fromWishListId:Long!=0, "目标心愿单Id" toWishListId:Long!=0):Boolean!
    fun deleteCollItems() {
        viewModelScope.launch {
            var items = arrayListOf<CollectItem>()
            record2Items.forEach { prdF ->
                prdF.wishItem.id?.let {
                    items.add(
                        CollectItem(
                            id = prdF.wishItem.id!!,
                            type = prdF.wishItem.type.optional(),
                            outOfferId = Optional.present(prdF.wishItem.outOfferId)
                        )
                    )
                }
            }
            var result = SkGqlClient.skMutation(
                MoveProductList2WishListMutation(
                    items = Optional.present(items),
                    fromWishListId = Optional.present(mWishlistId!!),
                    toWishListId = Optional.present(0),
                ),
                showDefaultLoading = true
            )?.data?.moveProductList2WishList
            if (result == true) {

                deleteMutiChoiceData()
                FlowBus.with<Int>(FlowConst.WISH_ALL_ITEMS_SHOW_TOAST_1)
                    .post(items.size)
                YYLogUtils.e(" #######startIndex11   ${0}")
            }
        }
    }


    fun deleteMutiChoiceData() {

        //这里的下标不能取0 因为用户插入是无序的 要用需要排序一次  取最小值 但是因为要刷总数 所以这里暂时用不到
//                val startIndex = record2Items[0].position
        record2Items.forEach { prdF ->
            mAllItemsObserver.value!!.remove(prdF)
        }


        //同步第一项
        mWishTotalNum -= record2Items.size

        record2Items.clear()
        recordIds.clear()

        if (mAllItemsObserver.value!!.size == 0) {
            mAllItemsObserver.value!!.add(0, RvNoBoardsEntry())
        }
        mAllItemsObserver.postValue(mAllItemsObserver.value)
    }


    fun moveMutiChoiceData(moveData: ArrayList<BatchProductArrEntry>) {
        moveData.forEach { moveItem ->
            for (item in mAllItemsObserver.value!!) {
                if (item is RvBoardDetailsItemEntry && moveItem.id == item.wishItem.id) {
                    mAllItemsObserver.value!!.remove(item)
                    break
                }
            }
            for (item in record2Items) {
                if (item is RvBoardDetailsItemEntry && moveItem.id == item.wishItem.id) {
                    record2Items.remove(item)
                    break
                }
            }
            recordIds.remove(moveItem.id)
        }
        //同步第一项
        mWishTotalNum -= moveData.size
        if (mAllItemsObserver.value!!.size == 0) {
            mAllItemsObserver.value!!.add(0, RvNoBoardsEntry())
        }
        mAllItemsObserver.postValue(mAllItemsObserver.value)
    }


    /**
     * 刷新底部选项 同时记录选中数据
     */
    fun refreshChoiceNum(): Int {
//        if (allCheck) {
//            choiceNum = mAllItemsObserver.value!!.size
//            return choiceNum
//        }
        var num = 0
        recordIds.clear()
        record2Items.clear()
        mAllItemsObserver.value!!.forEach {
            if (it is RvBoardDetailsItemEntry && it.hasChoice) {
                num++
                it.wishItem.id?.let { prdId ->
                    recordIds.add(prdId)
                    record2Items.add(it)
                }
            }
        }
        choiceNum = num
        return choiceNum
    }


    /**
     * 刷新底部选项 同时记录选中数据
     */
    var productCount = 0
    fun refreshItemsNum(init: Boolean = false, count: Int): String {
        if (init) {
            productCount = count
        } else {
            productCount += count
        }
        return if (productCount < 1) "$productCount item" else "$productCount items"
    }


    fun clearChoiceHistory() {
        selectAll = false
        recordIds.clear()
        record2Items.clear()
        choiceNum = 0
    }


    fun reNameF(wishlist: WishlistRenameEntry, hasChange: (b1: Boolean) -> Unit) {
        viewModelScope.async {
            var list = SkGqlClient.skMutation(
                UpdateWishMutation(
                    wishListUpdateRequest = WishListUpdateRequest(
                        id = wishlist.id,
                        title = wishlist.title,
                        description = wishlist.desc.optional()
                    )
                ),
                showDefaultLoading = true,
            )?.data?.updateWishList
            list.let {
                if (it == true) {
                    hasChange.invoke(true)
                } else {
                    hasChange.invoke(false)
                }
            }
        }
    }

    var wishlistLiveData: MutableResult<WishListF> =
        MutableResult()
    var userInfoLiveData: MutableResult<AccountF> =
        MutableResult()

    fun getWishlistAndUserInfo(h5WishListId: String, userId: String? = null) {
        viewModelScope.launch {
            val response = SkGqlClient.skQuery(
                FetchWishListByIdQuery(wishListId = h5WishListId),
                showDefaultLoading = true
            )
            if (response?.data?.fetchWishListById != null) {
                wishlistLiveData.value = response.data!!.fetchWishListById!!.wishListF
            } else if (response?.errors != null) {
                // {"errors":[{"message":"wishList not found","locations":[{"line":1,"column":47}],"path":["fetchWishListById"],"extensions":{"code":"311015004","message":"wishList not found","classification":"DataFetchingException"}}],"data":{"fetchWishListById":null}}
                if (response.findErrorCode(BaseApiCodeAndUrl.CODE_311015004)) {
                    toast("WishList Deleted")
                }
            }

            userId?.let {
                SkGqlClient.skQuery(
                    FetchAccountInfoByIdQuery(accountId = userId),
                    showDefaultLoading = true
                )?.data?.fetchAccountInfoById?.let {
                    userInfoLiveData.value = it.accountF
                }
            }
        }
    }


    fun getCurrentItemDataSize(): Int {
        var num = 0
        mAllItemsObserver.value?.forEach {
            if (it is RvBoardDetailsItemEntry) {
                num++
            }
        }
        return num
    }


    fun getRelatedIndex(): Int {
        var num = 0
        for ((index, item) in mAllItemsObserver.value!!.withIndex()) {
            if (item is RvRelatedTitleEntry) {
                num = index
                break
            }
        }
        return num
    }
}

